//
//  YZMKLinePacket.m
//  YZMicroStock
//
//  Created by wangminhong on 16/4/12.
//  Copyright © 2016年 cqjr. All rights reserved.
//

#import "YZMKLinePacket.h"
#import "YZMKLineItem.h"
#import <DateTools/DateTools.h>

@implementation YZMKLinePoint


- (NSString *)timeStr
{
    NSDate *date = [NSDate dateWithTimeIntervalSince1970: self.time/1000.0];
    
    return [date formattedDateWithFormat: @"MM/dd"];
}

@end

@implementation YZMKLinePacket{
    NSArray *_klineItems;
    NSMutableArray *_avgLines;
    
    //辅助计算
    NSInteger _basicIndex;
    NSInteger _windowCount;
    double _maxPrice;
    double _minPrice;
    double _maxVolume;
}


- (instancetype)init
{
    self = [super init];
    if (self) {
        _windowCount = 50;
        _basicIndex = 0;
    }
    return self;
}

- (void)_calculateAvgLines
{
    if (_avgLines == nil) {
        _avgLines = [NSMutableArray array];
    }
    
    [_avgLines removeAllObjects];
    [_avgLines addObject: [self avgLineForPeriod: 5]];
    [_avgLines addObject: [self avgLineForPeriod: 10]];
    [_avgLines addObject: [self avgLineForPeriod: 20]];
    [_avgLines addObject: [self avgLineForPeriod: 30]];
    
}

- (void)setOriginItems: (NSArray *)items
{
    _klineItems = [items copy];
    
    [self _calculateAvgLines];
}

- (void)updateFromItems: (NSArray *)items
{
    NSMutableArray *array = _klineItems.mutableCopy;
    for (YZMKLineItem *item in items) {
        NSInteger count = array.count;
        for (NSInteger i = count - 1; i >= 0; i--) {
            YZMKLineItem *ori = array[i];
            if (ori.time < item.time) {
                [array insertObject: item atIndex: i+1];
                break;
            }
            else if (ori.time == item.time)
            {
                [array replaceObjectAtIndex: i withObject: item];
                break;
            }
        }
    }
    _klineItems = [array copy];
    [self _calculateAvgLines];
}

- (NSArray *)avgLineForPeriod: (NSInteger)period
{
    NSMutableArray *avergeArray = [NSMutableArray array];
    
    double total = 0;
    for (NSInteger i = 0; i < _klineItems.count; i++) {
        YZMKLineItem *item = _klineItems[i];
        if (i < period) {
            total += item.price;
        }
        else
        {
            YZMKLineItem *preItem = _klineItems[i-period];
            total += item.price - preItem.price;
        }
        double avg = total / period;
        [avergeArray addObject: @(avg)];
    }
    return [avergeArray copy];
}

- (void)_updateLimits
{
    _maxVolume = 0;
    _maxPrice = .0;
    _minPrice = FLT_MAX;
    for (NSInteger i = _basicIndex; i < _klineItems.count && i < _basicIndex + _windowCount; i++) {
        YZMKLineItem *item = _klineItems[i];
        
        if (item.high > _maxPrice) {
            _maxPrice = item.high;
        }
        if (item.volume > _maxVolume) {
            _maxVolume = item.volume;
        }
        if (item.low  < _minPrice) {
            _minPrice = item.low;
        }
        
//        int lineOffset[] = {4,9,14,19};
//        for (NSInteger j = 0; j < 4; j++) {
//            NSArray *line = _avgLines[j];
//            if (i >= lineOffset[j]) {
//                double value = [line[i] doubleValue];
//                if (value > _maxPrice) {
//                    _maxVolume = value;
//                }
//                
//                if (value < _minPrice) {
//                    _minPrice = value;
//                }
//            }//end if i
//        }//end for j
    } // end for i
}

- (NSArray *)klineDrawPoints
{
    //TODO: allow config
    if (_klineItems.count == 0) {
        _maxPrice = 0;
        _maxVolume = 0;
        _minPrice = 0;
        return nil;
    }
    
    [self _updateLimits];
    
    NSMutableArray *resArray = [NSMutableArray array];
    for (NSInteger i = _basicIndex; i < _klineItems.count && i < _basicIndex + _windowCount; i++) {
        YZMKLineItem *item = _klineItems[i];
        
#warning maybe divide 0
        YZMKLinePoint *point = [[YZMKLinePoint alloc] init];
        point.time = item.time;
        point.open = (_maxPrice - item.open) / (_maxPrice - _minPrice);
        point.close = (_maxPrice - item.price) / (_maxPrice - _minPrice);
        point.highest = (_maxPrice - item.high) / (_maxPrice - _minPrice);
        point.lowest  = (_maxPrice - item.low) / (_maxPrice - _minPrice);
        point.amount = 1.0 * item.volume / _maxVolume;
        point.rise = (item.price > item.open);
        
        double avg1 = (_maxPrice - [_avgLines[0][i] doubleValue]) / (_maxPrice - _minPrice);
        double avg2 = (_maxPrice - [_avgLines[1][i] doubleValue]) / (_maxPrice - _minPrice);
        double avg3 = (_maxPrice - [_avgLines[2][i] doubleValue]) / (_maxPrice - _minPrice);
        double avg4 = (_maxPrice - [_avgLines[3][i] doubleValue]) / (_maxPrice - _minPrice);
        point.avgPoints = @[@(avg1), @(avg2), @(avg3), @(avg4)];
        
        [resArray addObject: point];
    }
    return resArray;
}


- (YZMKLineItem *)itemOfIndex: (NSInteger)index
{
    if (index < 0) {
        index = 0;
    }
    if (_klineItems.count > index) {
        return _klineItems[index];
    }
    else
    {
        return [_klineItems lastObject];
    }
}

- (NSInteger)itemCount
{
    return _klineItems.count;
}

- (BOOL)hasData
{
    return (_klineItems.count > 0);
}

- (void)clearData
{
    _maxPrice = 0;
    _minPrice = 0;
    _maxVolume = 0;
    _klineItems = nil;
    
}


@end
